/**
 * 滑块验证码
 * @function init 初始化滑块验证码
 */

var _fn,
  touchDistance = 0,
  sliderWidth = 0

const sysInfo = wx.getSystemInfoSync()

Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  /**
   * 组件的属性列表
   */
  properties: {},

  /**
   * 组件的初始数据
   */
  data: {
    filePath: "", // 图片的临时文件
    src: "",
    width: 150,
    height: 75,
    show: false,
    block: 40,
    top: 0,
    left: 0,
    pixelRatio: 1,
    transition: "transition"
  },

  /**
   * 组件生命周期函数-在组件实例进入页面节点树时执行
   */
  attached: function() {
    // this.show()
    sliderWidth = _fn.toPx(80) // 滑块的大小
  },

  /**
   * 组件的方法列表
   */
  methods: {
    show: function(options = {}) {
      this.onError = options.onError || null // 发生错误

      this.verifyBg = null // 清空画布
      this.verifyBlock = null // 清空画布

      this.setData({
        src: "",
        left: 0
      })
      _fn.init.call(this, options.config || {})
    },
    touchstart: function(e) {
      this.setData({
        transition: ""
      })
      touchDistance = e.touches[0].pageX
    },
    touchmove: function(e) {
      var left = e.touches[0].pageX - touchDistance + this.data.left
      touchDistance = e.touches[0].pageX

      if (left >= 0 && left <= this.data.width * 0.95 - sliderWidth) {
        this.setData({
          left: left
        })
      }
    },
    touchend: function(e) {
      this.setData({
        transition: "transition"
      })
    }
  }
})

_fn = {
  /**
   * 初始化组件内容
   * @param {Object} config 传入的配置参数
   */
  init: function(config = null) {
    _fn.initConfig.call(this, config) // 初始化配置（宽高等）
    console.log("请求图片中")
    // 初始化图片
    _fn
      .initImg(this.imgUrl)
      .then(({ path }) => {
        this.filePath = path // 存储画布需要的图片文件
        console.log("临时文件")
        // 初始化画布
        _fn.drawCanvas
          .call(this)
          .then(res => {})
          .catch(res => {})
      })
      .catch(res => this.onError && this.onError(res)) // 请求图片有误
  },

  /**
   * 初始化项目配置.包括默认配置
   * @param {Object} config
   */
  initConfig: function(config = {}) {
    config.width = _fn.toPx(config.width || 750)
    config.height = _fn.toPx(config.height || 375)
    config.block = _fn.toPx(config.block) || 32
    Object.assign(
      this,
      {
        imgUrl: `https://picsum.photos/300/150/?image=${_fn.getRandom(0, 1048)}`,
        // imgUrl: "https://picsum.photos/300/150/?image=1004",
        randomX: [config.block * 1, config.width - config.block * 1.5], // 随机宽度的位置
        randomY: [config.block, config.height - config.block * 1.5] // 随机高度的位置范围
      },
      config
    )

    console.log(this.randomX)
    console.log(this.randomY)
    this.setData({
      width: config.width,
      height: config.height,
      block: config.block,
      pixelRatio: sysInfo.pixelRatio,
      show: true
    })
  },
  /**
   * 获取一个随机数
   * @param {Number} start 随机数最小值
   * @param {Number} end 随机数最大值
   */
  getRandom: function(min, max) {
    return Math.round(Math.random() * (max - min) + min)
  },

  /**
   * 初始化图片
   */
  initImg: function(imgUrl = null) {
    return new Promise((resolve, reject) => {
      wx.getImageInfo({
        src: imgUrl,
        success(res) {
          resolve({ path: res.path })
        },
        fail(res) {
          reject(res) // res.errMsg
        }
      })
    })
  },

  /**
   * 绘制canvas
   */
  drawCanvas: function() {
    return new Promise((reject, resolve) => {
      console.log("绘制")
      Object.assign(this, _fn.getBlockInfo.call(this))

      // 绘制拼图板块
      this.verifyBg = wx.createCanvasContext("verifyBg", this) // 初始化canvas
      this.verifyBlock = wx.createCanvasContext("verifyBlock", this) // 初始化canvas

      // 初始化背景
      this.verifyBg.drawImage(this.filePath, 0, 0, this.width, this.height)

      _fn.drawBlock(this.verifyBg, this.blockInfo, "fill")
      _fn.drawBlock(this.verifyBlock, this.ratioInfo, "clip")

      this.verifyBlock.drawImage(this.filePath, 0, 0, this.width * sysInfo.pixelRatio, this.height * sysInfo.pixelRatio)

      console.log("普通作画")

      this.verifyBg.draw(false)
      var _this = this
      console.log("背景渲染")
      console.log(this.verifyBlock, "模块的canvas")
      this.verifyBlock.draw(false, function(params) {
        console.log("？？？", "导出渲染")
        wx.canvasToTempFilePath(
          {
            x: _this.ratioInfo.x,
            y: _this.ratioInfo.y,
            width: _this.ratioInfo.w * 1.5,
            height: _this.ratioInfo.w * 1.5,
            destWidth: _this.ratioInfo.w * 1.5,
            destHeight: _this.ratioInfo.w * 1.5,
            canvasId: "verifyBlock",
            success: res => {
              console.log("隐藏把")
              _this.setData({
                src: res.tempFilePath,
                top: _this.blockInfo.y,
                left: 0
              })
              console.log(_this.data.src)
            },
            fail: res => {
              console.log(res, "fail")
            },
            complete: res => {
              console.log(res, "最后，失败了？？")
            }
          },
          _this
        )
      })
    })
  },

  /**
   * 获取block的xy位置
   */
  getBlockInfo: function() {
    var info = {
      x: _fn.getRandom(this.randomX[0], this.randomX[1]),
      y: _fn.getRandom(this.randomY[0], this.randomY[1]),
      r: this.block / 4,
      w: this.block
    }

    return {
      blockInfo: info,
      ratioInfo: {
        x: info.x * sysInfo.pixelRatio,
        y: info.y * sysInfo.pixelRatio,
        r: info.r * sysInfo.pixelRatio,
        w: info.w * sysInfo.pixelRatio
      }
    }
  },

  /**
   * 绘制拼图模块
   */
  drawBlock: function(ctx, blockInfo, type) {
    let x = blockInfo.x,
      y = blockInfo.y,
      r = blockInfo.r,
      w = blockInfo.w
    let PI = Math.PI

    //绘制
    ctx.beginPath()
    //this.data.left+left
    ctx.moveTo(x, y)
    //top
    ctx.arc(x + (w + r) / 2, y, r, -PI, 0, true)
    ctx.lineTo(x + w + r, y)
    //right
    ctx.arc(x + w + r, y + (w + r) / 2, r, 1.5 * PI, 0.5 * PI, false)
    ctx.lineTo(x + w + r, y + w + r)
    //bottom
    ctx.arc(x + (w + r) / 2, y + w + r, r, 0, PI, false)
    ctx.lineTo(x, y + w + r)
    ctx.arc(x, y + (w + r) / 2, r, 0.5 * PI, 1.5 * PI, true)
    ctx.lineTo(x, y)
    //修饰，没有会看不出效果
    ctx.lineWidth = 2
    ctx.fillStyle = "rgba(255, 255, 255, 0.7)"
    ctx.strokeStyle = "rgba(255, 255, 255, 0.7)"
    ctx.stroke()
    ctx[type]()
    ctx.globalCompositeOperation = "xor"

    // 重置画笔颜色
    ctx.fillStyle = "rgba(255, 255, 255, 1)"
    ctx.strokeStyle = "rgba(255, 255, 255, 1)"
  },

  /**
   * rpx参数转为对应真机的px像素
   * @param {Number} rpx 传入rpx
   * @return {Number} 返回对应真机上的px像素
   */
  toPx: function(rpx) {
    return rpx / (750 / sysInfo.windowWidth)
  }
}
